package org.social.manager;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.bean.ActivityEntryInfo;
import org.bean.ActivityInfo;
import org.constant.ActionEnum;
import org.constant.ActivityConstant;
import org.constant.smallkey.ActivitySmallKey;
import org.error.GameErrorCode;
import org.social.db.bean.Activity;
import org.social.db.bean.ActivityEntry;
import org.social.db.cache.ActivityCache;
import org.social.db.cache.ActivityEntryCache;
import org.utils.RemoteUtil;

import com.google.common.collect.Maps;
import com.sojoys.artifact.tools.ToolError;
import com.xiaoleilu.hutool.bean.BeanUtil;
import com.xiaoleilu.hutool.date.DateUnit;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;

/**
 * @author : DengYing
 * @CreateDate : 2018年3月6日 下午12:10:19
 * @Description ：活动管理
 */
public class ActivityManager {
	
	
	static final Log log = LogFactory.get(ActivityManager.class);
	
	private ActivityManager() {
	}

	private static ActivityManager ME = new ActivityManager();

	public static ActivityManager me() {
		return ME;
	}

	public void notifyRemote(String serverId) {
		List<Activity> list = ActivityCache.me().loadAll();
		List<ActivityInfo> notifyList = new ArrayList<>(list.size());
		ActivityInfo activityInfo = null;
		for (Activity activity : list) {
			// 只同步开启的活动
			if (activity.getStatus() == ActivityConstant.RUNING) {
				activityInfo = buildActivityInfo(activity, ActionEnum.DEFAULT);
				notifyList.add(activityInfo);
			}
		}

		RemoteUtil.gameAsyn(serverId).noticeActivity(notifyList);
	}

	public void notifyActivity(List<Activity> activitys,ActionEnum action){
		List<ActivityInfo> notifyList = new ArrayList<>(activitys.size());
		for (Activity activity : activitys) {
			notifyList.add(buildActivityInfo(activity, action));
		}
		if (!notifyList.isEmpty()) {
			RemoteUtil.gameTopic().noticeActivity(notifyList);			
		}
	}
	
	/** 检查活动状态 */
	public void checkActivityStatus() {
		List<Activity> activitys = ActivityCache.me().loadAll();
		Date nowDate = new Date();
		// 需要通知的活动
		List<ActivityInfo> notifyList = new ArrayList<>(activitys.size());
		
		ActivityInfo activityInfo = null;
		for (Activity activity : activitys) {
			if (activity.getStatus() == ActivityConstant.AWAIT && activity.isActive()) {
				if (activity.getStartDate() == null || activity.getStartDate().before(nowDate)) {
					// 开启活动
					activity.setStatus(ActivityConstant.RUNING);
					
					// 初始化活动
					initActivity(activity);
					
					activityInfo = buildActivityInfo(activity, ActionEnum.ADD);
					notifyList.add(activityInfo); 
					
					log.debug("************ 活动开启 ID = {}",activity.getId());
				}
			}else if (activity.getStatus() == ActivityConstant.RUNING) {
				boolean close = false;
				if (activity.isActive()) {
					if (activity.getEndDate() != null && activity.getEndDate().before(nowDate)) {
						close = true;
					}
				}else {
					close = true;
				}
				
				if (close) {
					activity.setStatus(ActivityConstant.END);
					activity.update();
					activityInfo = buildActivityInfo(activity, ActionEnum.REMOVE);
					notifyList.add(activityInfo);
					log.debug("************ 活动关闭 ID = {}",activity.getId());
				}
			}
			
			// 触发运行中的活动
			if (activity.getStatus() == ActivityConstant.RUNING) {
				if(triggerActivityEntry(nowDate, activity)){
					activityInfo = buildActivityInfo(activity, ActionEnum.UPDATE);
					notifyList.add(activityInfo);
					log.debug("************ 活动触发 ID = {}",activity.getId());
				}
				if(checkActivityReset(nowDate, activity)){
					activityInfo = buildActivityInfo(activity, ActionEnum.RESET);
					notifyList.add(activityInfo);
					log.debug("************ 活动重置 ID = {}",activity.getId());
				}
			}
		}
		
		// 通知活动修改
		if (!notifyList.isEmpty()) {
			RemoteUtil.gameTopic().noticeActivity(notifyList);			
		}
	}
	/**
	 * 检查活动重置
	 * @param nowDate
	 * @param activity
	 * @return
	 */
	private boolean checkActivityReset(Date nowDate, Activity activity) {
		boolean reset = false;
		switch (activity.getResetType()) {
		case ActivityConstant.RESET_TYPE_DAY:
			reset = DateUtil.betweenDay(activity.getResetDate(), nowDate, true) > 0;
			break;
		case ActivityConstant.RESET_TYPE_MONTH:
			// 此处为hutool3.x版本 4.x需要修改参数
			reset = DateUtil.betweenMonth(activity.getResetDate(), nowDate, false) > 0;
			break;
		}
		if (reset) {
			List<ActivityEntry> entrys = activity.getActivityEntrysFkActivityId();
			for (ActivityEntry entry : entrys) {
				entry.getExtend().clear();
				entry.update();
			}
			activity.setResetDate(nowDate);
			activity.update();
		}
		return reset;
	}
	
	/**
	 * 初始化活动开启
	 * @param activity
	 */
	private void initActivity(Activity activity) {
		// 每开启一次版本号+1
		activity.setVer(activity.getVer()+1);
		activity.setResetDate(new Date());
		List<ActivityEntry> entrys = activity.getActivityEntrysFkActivityId();
		for (ActivityEntry entry : entrys) {
			entry.getExtend().clear();
			entry.update();
		}
		activity.update();
	}

	/** 触发活动 */
	private boolean triggerActivityEntry(Date nowDate, Activity activity) {
		boolean trigger = false;
		if (activity.getType() == ActivityConstant.ACTIVITY_TYPE_AP_SUPPLY) {
			List<ActivityEntry> entrys = activity.getActivityEntrysFkActivityId();
			for (ActivityEntry activityEntry : entrys) {
				boolean bool = filterEntry(activity, activityEntry);
				if (!bool) {
					continue;
				}
				int status = MapUtils.getIntValue(activityEntry.getExtend(), ActivitySmallKey.STATUS);
				int entry_trigger_time_type = MapUtils.getIntValue(activityEntry.getRemark(), ActivityConstant.ENTRY_TRIGGER_TIME_TYPE);
				int entry_trigger_begin_time = MapUtils.getIntValue(activityEntry.getRemark(), ActivityConstant.ENTRY_TRIGGER_BEGIN_TIME);
				int entry_trigger_end_time = MapUtils.getIntValue(activityEntry.getRemark(), ActivityConstant.ENTRY_TRIGGER_END_TIME);
				Date beginDate = DateUtil.beginOfDay(nowDate);
				
				int nowSecond = (int) DateUtil.between(beginDate, nowDate, DateUnit.SECOND);
				
				switch (status) {
				case ActivityConstant.ENTRY_STATUS_RUNING:
					if (nowSecond >= entry_trigger_begin_time && nowSecond <= entry_trigger_end_time) {
						activityEntry.getExtend().put(ActivitySmallKey.STATUS, ActivityConstant.ENTRY_STATUS_FINISH);
						trigger = true;
					}
					break;
				case ActivityConstant.ENTRY_STATUS_FINISH:
					if (nowSecond < entry_trigger_begin_time || nowSecond > entry_trigger_end_time) {
						activityEntry.getExtend().put(ActivitySmallKey.STATUS, ActivityConstant.ENTRY_STATUS_RUNING);
						trigger = true;
					}
					break;
				}
				
				if (bool) {
					activityEntry.update();
				}
			}
		}
		return trigger;
	}
	
	// 信息构建
	private ActivityInfo buildActivityInfo(Activity activity, ActionEnum action) {
		ActivityInfo activityInfo = new ActivityInfo();
		BeanUtil.copyProperties(activity, activityInfo);
		activityInfo.setAction(action);
		
		// 活动条目信息
		List<ActivityEntry> entrys = activity.getActivityEntrysFkActivityId();
		Map<Integer, ActivityEntryInfo> entryMaps = new HashMap<>(entrys.size());
		ActivityEntryInfo entryInfo = null;
		for (ActivityEntry activityEntry : entrys) {
			// 只传输激活的条目
			if (activityEntry.isActive() && filterEntry(activity, activityEntry)) {
				entryInfo = new ActivityEntryInfo();
				BeanUtil.copyProperties(activityEntry, entryInfo);
				entryMaps.put(entryInfo.getId(), entryInfo);
			}
		}
		activityInfo.setEntrys(entryMaps);
		
		return activityInfo;
	}
	
	/** 条目过滤器 */
	private boolean filterEntry(Activity activity,ActivityEntry activityEntry){
		boolean bool = activityEntry.isActive();
		Map remark = activityEntry.getRemark();
		switch (activity.getType()) {
		case ActivityConstant.ACTIVITY_TYPE_MONTH_SIGN:
			int month = DateUtil.thisMonth();
			int group = MapUtils.getIntValue(remark,ActivityConstant.ENTRY_REMARK_GROUP);
			bool = (group != (month % 2) + 1);
			
			if (bool) {
				Date now = new Date();
				int dayCount = (int) (DateUtil.betweenDay(DateUtil.beginOfMonth(now), DateUtil.endOfMonth(now), true) + 1);
				if (activityEntry.getProgress() > dayCount) {
					bool = false;
				}
			}
			
			break;
		}
		return bool;
	}
	
	/**
	 * 上传活动状态
	 * @param activityId
	 * @param entryId
	 * @param pid
	 * @param status
	 */
	public void uploadActivityEntryStatus(int activityId, List<Integer> entryIds, int pid, int status) {
		Activity activity = ActivityCache.me().getById(activityId);
		ToolError.isAndTrue(GameErrorCode.NOT_FOND_ACTIVITY, activity == null);
		ActivityEntry entry = null;
		for (int entryId : entryIds) {
			entry = ActivityEntryCache.me().getById(entryId);
			ToolError.isAndTrue(GameErrorCode.NOT_FOND_ACTIVITY_ENTRY, entry == null);
		}
		
		for (Integer entryId : entryIds) {
			entry = ActivityEntryCache.me().getById(entryId);
			Map<Integer, Integer> entryMap = (Map<Integer, Integer>) entry.getExtend().computeIfAbsent(ActivitySmallKey.SUBMIT_LOG, k -> Maps.newHashMap());
			entryMap.put(pid, status);
			entry.update();
		}
	}
}
